package kz.kstu.ds.verify;

import kz.kstu.ds.entity.SignedDocument;
import kz.kstu.ds.xml.JAXBHelper;
import sun.misc.BASE64Decoder;

import javax.xml.bind.JAXBException;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.KeyFactory;
import java.security.PublicKey;
import java.security.Signature;
import java.security.spec.X509EncodedKeySpec;

/**
 * Date: 05.11.12
 * Time: 0:02
 *
 * @author Oleg Anastassov
 */
public class SignatureVerifier {

    // The public key used to verify the digital signature.
    private PublicKey publicKey;

    public SignatureVerifier() {
    }

    public SignatureVerifier(byte[] publicKeyBytes) throws GeneralSecurityException {
        super();
        initPublicKey(publicKeyBytes);
    }

    private SignatureVerifier(String filePath) throws IOException, GeneralSecurityException {
        FileInputStream input = new FileInputStream(filePath);
        byte[] keyBytes = new byte[input.available()];
        input.read(keyBytes);
        input.close();
        initPublicKey(keyBytes);
    }

    // Create the public key instance, using the key bytes passed in.
    private void initPublicKey(byte[] publicKeyBytes)
            throws GeneralSecurityException {
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKeyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("DSA");
        this.publicKey = keyFactory.generatePublic(keySpec);
    }

    public boolean verifyDigitalSignature(byte[] signatureBytes,
                                          String message) throws GeneralSecurityException {
        Signature sig = Signature.getInstance("SHA1withDSA");
        sig.initVerify(publicKey);
        sig.update(message.getBytes());
        return sig.verify(signatureBytes);
    }

    public boolean verify(File doc, File key) throws JAXBException, FileNotFoundException {
        SignedDocument sd = JAXBHelper.unmarshal(doc);
        String content = sd.getContent();
        String signature = sd.getSignature();

        try {
            BASE64Decoder decoder = new BASE64Decoder();
            byte[] sigBytes = decoder.decodeBuffer(signature);

            // Verify the digital signature.
            SignatureVerifier sigVerify = new SignatureVerifier(key.getName());
            return sigVerify.verifyDigitalSignature(sigBytes, content);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

}
